博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django 图片上传upload_to路径指定失效的问题记录
阅读量:6502 次
发布时间:2019-06-24

本文共 6835 字,大约阅读时间需要 22 分钟。

  hot3.png

初始方法一:

疑虑:model使用upload_to自定义路径方法失效,指定路径也失效。最后以Views中指定MEDIA_URL和MEDIA_ROOT做拼接,并且自行判断并建立文件夹,手动chunk保存。不完美的解决。

model:    看avatar字段的upload_to

import uuidfrom django.db import modelsfrom django.contrib.auth.models import AbstractUserclass SysUser(AbstractUser):    """    用户扩展表,用于替换auth的user类,并添加头像和昵称。    """    uid = models.BigAutoField(primary_key=True)    nickname = models.CharField(max_length=32, verbose_name="昵称")    # 使用 models.ImageField 需要安装 Pillow ,cmd命令:pip install Pillow    avatar = models.ImageField(verbose_name="头像", upload_to="avatar11")    class Meta:        # 数据库显示的表名        db_table = "sys_user"

form:

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsclass EditUserForm(Form):    """..."""    e_avatar = fields.ImageField(        required=False,        widget=widgets.FileInput(attrs={"hidden": "hidden"})    )    """..."""

Views:

def upload_user_avatar(request):    """用户上传头像操作"""    if request.method == "POST":        user_id = request.user.uid        # 只是当前登录用户        ret = {'state': True, 'error': None, 'data': None}        # user_id = request.POST.get("uid", None)        avatar = request.FILES.get("avatar", None)        # 如果文件夹不存在,则建立        dir_path = os.path.join(MEDIA_ROOT, "users", "{}_{}".format(request.user.uid, request.user.username), "avatar")        if not os.path.exists(os.path.join(dir_path)):            os.makedirs(os.path.join(dir_path))        avatar_path = os.path.join(dir_path, avatar.name)        try:            with open(avatar_path, 'wb+') as img:                for chunk in avatar.chunks():                    img.write(chunk)                print("文件接收成功")            img_url = os.path.join("users", "{}_{}".format(request.user.uid, request.user.username), "avatar")            SysUser.objects.filter(uid=user_id).update(avatar=img_url)            ret["data"] = "头像更新成功"        except Exception as e:            ret["state"] = False            ret["data"] = "头像更新失败,请确认图片格式"            print(e)        return HttpResponse(json.dumps(ret))

html:

 

  • SysUser.objects.filter(uid=user_id).update(avatar=img_url)
  • 这句话执行结束后,只保存文件名,无法使用upload_to指定的路径。
  • 页面加载时,直接使用拼接后路径。

初始方法二:

TMD,一个保存方式的问题,竟然能啰啰嗦嗦这么久。以后以此方法操作。

model:不变

views:

def upload_user_avatar(request):    """用户上传头像操作"""    if request.method == "POST":        user_id = request.user.uid        # 只是当前登录用户        ret = {'state': True, 'error': None, 'data': None}        avatar = request.FILES.get("avatar", None)        try:            user_obj = SysUser.objects.filter(uid=user_id).first()            user_obj.avatar = avatar            user_obj.save()            ret["data"] = "头像更新成功"        except Exception as e:            ret["state"] = False            ret["data"] = "头像更新失败,请确认图片格式"            print(e)        return HttpResponse(json.dumps(ret))
  • user_obj.save()
  • 使用这种保存方式的好处:
  1. 会自动保存文件路径到数据库
  2. 会自动保存文件到指定路径
  3. 必要时会自动创建目录。

目前最终方法:

model:

import uuidimport osfrom django.db import modelsfrom django.contrib.auth.models import AbstractUser"""python-cmd : makemigrationspython-cmd : migrate"""def user_directory_path(instance, filename):    """用户上传文件时的自定义操作"""    ext = filename.split('.')[-1]                           # 获取上传的文件名的后缀    filename = '{0}.{1}'.format(uuid.uuid4().hex[:8], ext)  # 修改文件名,谨防重名。(文档说重名后,会自动增加后缀)    sub_folder = 'avatar'    # 日后如果对上传文件的类型进行归档时可以COPY这个做参考。    # if ext.lower() in ["jpg", "png", "gif", "ico"]:    #    sub_folder = "avatar"    # if ext.lower() in ["pdf", "docx"]:    #     sub_folder = "document"    return os.path.join("users", "%s-%s" % (instance.user.uid, instance.user.username), sub_folder, filename)class SysUser(AbstractUser):    """    用户扩展表,用于替换auth的user类,并添加头像和昵称。    """    uid = models.BigAutoField(primary_key=True)    nickname = models.CharField(max_length=32, verbose_name="昵称")    # 使用 models.ImageField 需要安装 Pillow ,cmd命令:pip install Pillow    avatar = models.ImageField(verbose_name="头像", upload_to=user_directory_path)    class Meta:        # 数据库显示的表名        db_table = "sys_user"

form:

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsclass EditUserForm(Form):    """..."""    e_avatar = fields.ImageField(        required=False,        widget=widgets.FileInput(attrs={"hidden": "hidden"})    )    """页面操作该元素时,使用的ajax方式,所以仅对此项进行操作。未使用EditUserForm做验证等操作。"""    """..."""

views:

def upload_user_avatar(request):    """用户上传头像操作"""    if request.method == "POST":        user_id = request.user.uid        # 只是当前登录用户        ret = {'state': True, 'error': None, 'data': None}        # user_id = request.POST.get("uid", None)   # 如果以后有需求修改其他人的信息时,再从页面获取。        avatar = request.FILES.get("avatar", None)        try:            user_obj = SysUser.objects.filter(uid=user_id).first()            user_obj.avatar = avatar            user_obj.save()            ret["data"] = "头像更新成功"        except Exception as e:            ret["state"] = False            ret["data"] = "头像更新失败,请确认图片格式"            print(e)        return HttpResponse(json.dumps(ret))

html:

JS:

// 上传文件按钮(label里的图片)点击事件$('#id_e_avatar').on('change',function () {	// 文件上传之前在本地加载预览。	{		// 获取用户最后一次选择的图片		var choose_file=$(this)[0].files[0];		// 创建一个新的FileReader对象,用来读取文件信息		var reader=new FileReader();		// 读取用户上传的图片的路径		reader.readAsDataURL(choose_file);		// 读取完毕之后,将图片的src属性修改成用户上传的图片的本地路径		reader.onload=function () {			 $("#avatar-img").attr("src",reader.result)		}	}	// 使用FormData格式,将文件上传至服务器	formdata = new FormData();	//formdata.append('uid',$('#id_e_id').val());	formdata.append("avatar",$("#id_e_avatar")[0].files[0]);	$.ajax({		type: "POST",		url: "/account/upload_user_avatar",		data:formdata,		processData:false,	//上传文件时需要如此设置1		contentType:false,	//上传文件时需要如此设置2		success:function (data) {			data = JSON.parse(data);			console.log(data);			alert(data.data)	// 偷懒了,哈哈         }	});});

media_url映射:

from django.urls import path, re_path, includefrom django.views.generic.base import RedirectViewfrom django.views.static import serve    # 映射media_root路径,可以通过浏览器访问的操作-1from django.contrib.auth.decorators import login_requiredfrom WXH_DJANGOWEB import settingsfrom utils.required import requiredurlpatterns = [    path('account/', include("account.urls")),    path('blog/', include("blog.urls")),    re_path(r"^media/(?P
.*)$", serve, {"document_root": settings.MEDIA_ROOT, }) # 映射media_url,可以通过浏览器访问的操作-2]

至此,记录完毕。回家吃饭。坑爹的保存方式…… 愿同志们绕坑而行,用不遇坑。

转载于:https://my.oschina.net/asktao/blog/3004672

你可能感兴趣的文章
Jfinal Generator 不需要生成带某个前缀的表名数组的方法
查看>>
struts2中使用标签操作静态方法等
查看>>
熬夜写了一个小游戏,向SpaceX聊表敬意
查看>>
身份证工具类
查看>>
JPA增删改查,
查看>>
apache 开启 gzip 压缩服务
查看>>
python mysql
查看>>
开源 免费 java CMS - FreeCMS1.5-建站向导
查看>>
Selenium的延迟等待
查看>>
jquery 1.6以上版本 全选
查看>>
AppCan 学习
查看>>
flask框架
查看>>
《疯狂Java讲义》学习笔记(十)异常处理
查看>>
Lua(Codea) 中 table.insert 越界错误原因分析
查看>>
ELK 5.x日志分析 (二) Elasticserach 5.2 安装
查看>>
一次奇怪的AP注册异常问题处理
查看>>
TableStore: 海量结构化数据分层存储方案
查看>>
Unity 4.x游戏开发技巧集锦(内部资料)
查看>>
自适应网页设计
查看>>
获取BT节点信息bittorrent-discovery
查看>>